package com.yhb.controller;

import com.fasterxml.jackson.core.type.TypeReference;
import com.yhb.controller.vo.ArrayWrapperVo;
import com.yhb.controller.form.rpc.CpsOrder;
import com.yhb.controller.form.rpc.CpsReq;
import com.yhb.controller.form.rpc.Message;
import lombok.extern.log4j.Log4j;
import lombok.var;
import me.edzh.spring.bootstrap.model.Response;
import me.edzh.spring.bootstrap.processor.SignAndEncryptProcessor;
import me.edzh.spring.bootstrap.utils.JSONUtil;
import me.edzh.spring.bootstrap.utils.ResultCode;
import me.edzh.spring.bootstrap.utils.exception.ServiceException;
import me.edzh.spring.bootstrap.utils.security.AESUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import javax.annotation.PostConstruct;
import javax.crypto.spec.SecretKeySpec;
import java.security.Key;
import java.util.Base64;
import java.util.List;

@Log4j
@RestController
@RequestMapping("/rpc")
public class RPCController {

    @Value("${rpc.aesKey}")
    private String aesKeyString;
    @Value("${rpc.aesAlgorithm}")
    private String aesAlgorithm;

    @Autowired
    private SignAndEncryptProcessor signAndEncryptProcessor;

    private Key aesKey;

    @PostConstruct
    private void init() {
        byte[] raw = Base64.getDecoder().decode(aesKeyString);
        aesKey = new SecretKeySpec(raw, aesAlgorithm);
    }

    @PostMapping("/onOrders")
    public Response onOrder(@RequestBody byte[] bytes, @RequestHeader("SIGN") String sign) {
        var req = decodeBody(bytes, CpsReq.class, sign);
        List<CpsOrder> orders = JSONUtil.parseJson(req.getOrders(), new TypeReference<List<CpsOrder>>() {
        });


        return Response.ok();
    }

    @PostMapping("/onMessage")
    public Response onMessage(@RequestBody byte[] bytes, @RequestHeader("SIGN") String sign) {
        var message = decodeBody(bytes, Message.class, sign);

        return Response.ok();
    }


    private <T> T decodeBody(byte[] bytes, Class<T> resultType, String sign) {
        try {
            var decryptedBytes = AESUtils.decrypt(aesKey, bytes, aesAlgorithm);
            return signAndEncryptProcessor.checkSignAndConvertBody(sign, decryptedBytes, false, resultType);
        } catch (ServiceException e) {
            throw e;
        } catch (Exception e) {
            log.error("decrypt err:", e);
            throw new ServiceException(ResultCode.ERROR_DEFAULT_CODE, "err");
        }
    }
}
